package com.blackcat.annotation.conditional.config;

import com.blackcat.annotation.conditional.compent.City;
import com.blackcat.annotation.conditional.compent.MyAspect;
import com.blackcat.annotation.conditional.compent.MyLog;
import com.blackcat.annotation.conditional.compent.People;
import com.blackcat.annotation.conditional.conditional.MyCondition;
import org.springframework.boot.autoconfigure.condition.*;
import org.springframework.boot.system.JavaVersion;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;

/**
 * <p> 描述 ：容器加载Bean 加入条件判断
 * @author : blackcat
 * @date : 2020/5/23 16:08
 */
@Configuration
public class MyConfig {


    /**
     * 类路径是否有指定的值。
     * 如果我们要加载的 bean 依赖指定资源是否存在于 classpath 中，那么我们就可以使用这个注解。
     */
    /*@ConditionalOnResource(resources = "/test.properties")
    @Bean
    public People people() {
        return new People();
    }*/

    /**
     * 只有运行在 web 应用里才会加载这个 bean
     */
    /*@ConditionalOnWebApplication
    @Bean
    public People people() {
        return new People();
    }*/

    /**
     * 与@ConditionalOnWebApplication相反，在非 web 环境才加载 bean。
     */
    /*@ConditionalOnNotWebApplication
    @Bean
    public People people() {
        return new People();
    }*/

    /**
     * 在JNDI存在的条件下查找指定的位置。
     * 只有指定的资源通过 JNDI 加载后才加载 bean。
     * JNDI(Java Naming and Directory Interface,Java命名和目录接口)。
     */
    /*@ConditionalOnJndi("java:comp/env/foo")
    @Bean
    public People people() {
        return new People();
    }*/

    /**
     * 只有运行指定版本的 Java 才会加载 Bean
     */
    /*@ConditionalOnJava(JavaVersion.EIGHT)
    @Bean
    public People people() {
        return new People();
    }*/

    /**
     * 基于SpEL表达式作为判断条件。当括号中的内容为true时，使用该注解的类被实例化。
     * 其他写法：
     *      ConditionalOnExpression("${enabled:false}")
     *      ConditionalOnExpression("'${user.name}'.equals('zhang')")
     */
    /*@ConditionalOnExpression("1==1")
    @Bean
    public People people() {
        return new People();
    }*/

    /**
     * 当给定的类名在类路径上不存在，则实例化当前Bean。
     * 结果同ConditionalOnMClass相反。
     */
    /*@ConditionalOnMissingClass("com.blackcat.annotation.conditional.compent.City")
    @Bean
    public People people() {
        return new People();
    }*/

    /**
     * 当给定的类名在类路径上存在，则实例化当前Bean。
     * 原理同@ConditionalOnBean差不多。
     */
    /*@ConditionalOnClass(name = "com.blackcat.annotation.conditional.compent.City")
    @Bean
    public People people() {
        return new People();
    }*/

    /*@Bean
    public City city() {
        City city = new City();
        city.setCityName("千岛湖");
        return city;
    }*/

    /**
     * 这里加了ConditionalOnBean注解，就代表如果city存在才实例化people
     */
    /*@ConditionalOnBean(name = "city")
    @Bean
    public People people(City city) {
        //这里如果city实体没有成功注入 这里就会报空指针
        city.setCityCode(301701);
        return new People("小小", 3, city);
    }*/

    /**
     * 当给定的在bean不存在时,则实例化当前Bean。
     * 与ConditionalOnBean结果相反
     */
    /*@ConditionalOnMissingBean(name = "city")
    @Bean
    public People people() {
        return new People();
    }*/




    /*@Bean
    public MyAspect myAspect() {
        return new MyAspect();
    }*/

    /**
     * 有两个组件MyAspect，MyLog。现在有条件判断，当容器内没有MyAspect就不注入MyLog。
     */
    /*@Bean
    @Conditional(value = MyCondition.class)
    public MyLog myLog() {
        return new MyLog();
    }*/

    public static void main(String[] args) {
        // 容器中读取Bean
        AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(MyConfig.class);
        for(String beanName:ctx.getBeanDefinitionNames()) {
            System.out.println("beanName:"+beanName);
        }
    }

}
